﻿using System;
using AngleSharp.Html.Parser;
using Fetches.Custom.BaiduTradeDemo;
using Fetches.Custom.TestOrder;
using Fetches.Fetch.Dto;
using Fetches.Fetch.Factory;
using Fetches.Fetch.Fetcher;
using Serilog;

namespace OrderSubmit
{
    internal class Program
    {
        /*
       * 终端用户参与操作为创建FetchOrder提交给Factory,需要加工情况下指定Processor消费PagePool。
       * 开发人员参与的操作是定制工单，指定Fetcher、Processor,内置对象不能满足需求时进一步定制
       */
        private static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .Enrich.FromLogContext()
                .WriteTo.Console().WriteTo.File("logs/fetch.log", rollingInterval: RollingInterval.Day)
                .CreateLogger();

            var factory = LocalFetchFactory.CreateWithFilePersistence();
            //var factory = new RemoteFetchFactory("http://localhost:5000/");
            var receipt = DirectFetchDemo(factory); //直接新建Order爬取
            //WatchDemo(factory, receipt); //每隔5秒输出一次进度
            //ConsumeDemo(factory); //通过消费PagePool实现数据抽取
            //CustomOrderDemo(factory);//SiteOrder是简化的订单模型，缺点是暂时不支持提交到远程机器上执行
        }

        //总结 这个方法等价于控制中心的一个API.代码方式提交是为了完成更多的个性化设置
        private static FetchReceipt DirectFetchDemo(IFetchFactory factory)
        {
            //第一步 创建并设置工单
            var order = WebMagicOrder.CreateForTest();

            //第二步 提交工单,获得回执用于监控和消费
            var receipt = factory.Fetch<HttpClientFetcher>(order);
            return receipt;
        }

        private static void WatchDemo(IFetchFactory factory, FetchReceipt receipt)
        {
            //由工厂类主动通知进度，简化终端用户API
            factory.Watch(receipt, progress =>
            {
                Console.WriteLine(progress.Status == FetchTaskStatus.Solved ||
                                  progress.Status == FetchTaskStatus.Canceled
                    ? $"fetch task {receipt.Id} is finished,progress watch exit"
                    : $"fetching {receipt.Id},success {progress.Success} fail {progress.Failure} remains {progress.Remains}");
            });
        }

        //可以在爬取时或爬取后使用消费PagePool的方式来进行数据的加工存储
        private static void ConsumeDemo(IFetchFactory factory, FetchReceipt receipt = null)
        {
            if (receipt == null)
            {
                receipt = FetchReceipt.FromJsonFile("test.receipt");
            }

            var consumer = factory.Consume(receipt);
            consumer.AddPageProcessor(page =>
            {
                Console.WriteLine(
                    $"{page.ContentHash} url {page.Request.Url.OriginalString} 下载耗时{page.ElapsedMilliseconds}毫秒");
                var html = new HtmlParser().ParseDocument(page.SourceCode);
                Console.WriteLine(html.Title + "\t是" + (page.Request.IndexPage ? "索引页" : "内容页"));
            });
            consumer.StartConsume();
        }

        private static void CustomOrderDemo(IFetchFactory factory)
        {
            //FetchWithProcess相当于爬取三部曲+Consume，缺点是我没有支持SiteOrder分布式
            var baiduOrder = new BaiduTradeOrder();
            baiduOrder.FetchAndProcess(factory);
        }
    }
}